#pragma once
#include "BasicUdpClient.h"
#include "BasicDefine.h"
//#include <Winsock2.h>
#pragma comment(lib,"Ws2_32.lib")

namespace utility
{
	BasicUdpClient::BasicUdpClient(void): m_sock(INVALID_SOCKET)
		, m_bIsInit(false)
	{
	}

	BasicUdpClient::~BasicUdpClient(void)
	{
	}


	int BasicUdpClient::SendData( LPVOID pData, DWORD dwSize )
	{
		if (!m_bIsInit)
		{
			return FALSE;
		}

		DWORD nSent = 0;

		while (nSent < dwSize)
		{
			int nRet = ::sendto(m_sock, reinterpret_cast<LPCSTR>(pData), dwSize, 0, reinterpret_cast<LPSOCKADDR>(&m_addr), sizeof(m_addr));

			if (nRet == SOCKET_ERROR)
			{
				nRet = ::WSAGetLastError();

				if (nRet == WSAETIMEDOUT)
				{
					return WSAETIMEDOUT;
				}

				_XXM_LOG_OUT(_T("sendto error:%d"), nRet);
				return 0;
			}

			nSent += nRet;
		}

		return -1;
	}

	bool BasicUdpClient::SetSendTimeOut( int nTimeOut )
	{
		if (!m_bIsInit)
		{
			return false;
		}

		if (::setsockopt(m_sock, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast<LPCSTR>(&nTimeOut), sizeof(nTimeOut)) == SOCKET_ERROR)
		{
			_XXM_LOG_OUT(_T("setsockopt error:%d"), ::WSAGetLastError());
			return false;
		}

		return true;
	}

	bool BasicUdpClient::SetRecvTimeOut( int nTimeOut )
	{
		if (!m_bIsInit)
		{
			return false;
		}

		if (::setsockopt(m_sock, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<LPCSTR>(&nTimeOut), sizeof(nTimeOut)) == SOCKET_ERROR)
		{
			_XXM_LOG_OUT(_T("setsockopt error:%d"), ::WSAGetLastError());
			return false;
		}

		return true;
	}

	int BasicUdpClient::RecvData( LPVOID pData, DWORD& dwSize )
	{
		if (!m_bIsInit)
		{
			return 0;
		}

		DWORD nRecv = 0;
		int nAddrSize = sizeof(m_addr);

		int nRet = ::recvfrom(m_sock, reinterpret_cast<LPSTR>(pData), 1024, 0, reinterpret_cast<LPSOCKADDR>(&m_addr), &nAddrSize);

		if (nRet == SOCKET_ERROR)
		{
			nRet = ::WSAGetLastError();

			if (nRet == WSAETIMEDOUT)
			{
				return WSAETIMEDOUT;
			}

			_XXM_LOG_OUT(_T("recvfrom error:%d"), nRet);
			return 0;
		}
		dwSize = nRet;
		return -1;
	}

	bool BasicUdpClient::InitSocket( void )
	{
		WSADATA wsaData;

		if (::WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR)
		{
			_XXM_LOG_OUT(_T("WSAStartup error:%d"), ::WSAGetLastError());
			return false;
		}
		m_sock = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

		if (m_sock == INVALID_SOCKET)
		{
			_XXM_LOG_OUT(_T("socket error:%d"), ::WSAGetLastError());
			return false;
		}

		m_bIsInit = true;
		return true;
	}

	bool BasicUdpClient::SetServer( const char * pszDomain, unsigned short uPort )
	{
		PHOSTENT pHost = ::gethostbyname(pszDomain);

		if (pHost == NULL)
		{
			_XXM_LOG_OUT(_T("gethostbyname failed! err:"), ::WSAGetLastError());
			return false;
		}

		m_addr.sin_family = AF_INET;
		m_addr.sin_port = ::htons(uPort);
		m_addr.sin_addr = *reinterpret_cast<PIN_ADDR>(pHost->h_addr_list[0]);

		return true;
	}

	bool BasicUdpClient::UninitSocket( void )
	{
		//_XXM_LOG_OUT(__FUNCTIONW__);
		//_XXM_LOG_OUT(__FILEW__); //__FILE__
		//_XXM_LOG_OUT(__LINE__)

		if (m_bIsInit)
		{
			int nRet = ::closesocket(m_sock);

			if (nRet != 0)
			{
				_XXM_LOG_OUT(_T("closesocket failed, err:%d\r\n"), ::WSAGetLastError());
			}

			m_sock = INVALID_SOCKET;
			m_bIsInit = false;

			return !(nRet || ::WSACleanup());
		}

		return true;
	}


}
